package com.ysstech.system.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysstech.common.cache.RedisCacheManager;
import com.ysstech.common.entity.Menu;
import com.ysstech.common.entity.PageBean;
import com.ysstech.common.entity.Region;
import com.ysstech.common.entity.Role;
import com.ysstech.common.entity.Organization;
import com.ysstech.common.entity.User;
import com.ysstech.common.exception.BusinessException;
import com.ysstech.common.entity.TreeNode;
import com.ysstech.common.service.DicvalueService;
import com.ysstech.system.entity.RoleMenu;
import com.ysstech.system.entity.RoleRegion;
import com.ysstech.system.entity.UserRole;
import com.ysstech.system.enums.SystemEnum;
import com.ysstech.system.mapper.MenuMapper;
import com.ysstech.system.mapper.RegionMapper;
import com.ysstech.system.mapper.RoleMapper;
import com.ysstech.system.mapper.UserRoleMapper;
import com.ysstech.system.service.MenuService;
import com.ysstech.system.service.RoleMenuService;
import com.ysstech.system.service.RoleRegionService;
import com.ysstech.system.service.RoleService;
import com.ysstech.system.service.OrganizationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 角色服务实现类
 * </p>
 *
 * @author lishuangliang
 * @since 2020-09-11
 */
@Service(value = "roleService")
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private RoleRegionService roleRegionService;
    @Autowired
    private DicvalueService dicvalueService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RedisCacheManager redisCacheManager;

    /**
     * 查询角色列表信息
     *
     * @param role
     * @param pageBean
     * @return
     * @throws Exception
     */
    public PageBean<Role> queryAllRoles(Role role, PageBean pageBean) throws Exception {
        QueryWrapper<Role> wrapper = this.getQueryWrapper(role);
        IPage pageRole = this.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()), wrapper);
        this.switchedListRole(pageRole.getRecords());
        return new PageBean<>(pageRole);
    }

    /**
     * 批量删除角色
     *
     * @param ids
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteRole(List<String> ids) throws Exception {
        if (ids == null || ids.size() == 0) {
            throw new BusinessException("获取删除信息失败，请稍后重试！");
        }
        User user = redisCacheManager.getLoginUserInfo();
        for (Role role : user.getRoles()) {
            if (null == role) {
                continue;
            }
            if (ids.contains(role.getId())) {
                throw new BusinessException("不能删除自己所在的角色信息，请稍后重试！");
            }
        }
        //删除角色信息
        this.removeByIds(ids);
        //批量删除用户角色对应角色关系
        QueryWrapper<UserRole> wrapper = new QueryWrapper<>();
        wrapper.in("ROLE_ID", ids);
        userRoleMapper.delete(wrapper);
        //删除角色菜单和角色按钮表
        QueryWrapper<RoleMenu> wrappermenu = new QueryWrapper<>();
        wrappermenu.in("ROLE_ID", ids);
        roleMenuService.remove(wrappermenu);
        QueryWrapper<RoleRegion> wrapperregion = new QueryWrapper<>();
        wrapperregion.in("ROLE_ID", ids);
        roleRegionService.remove(wrapperregion);
    }

    /**
     * 处理角色拥有的权限默认勾选
     *
     * @return
     */
    public List<TreeNode> quertMenuByRoleId(String roleId) throws Exception {
        //查询角色拥有的菜单信息
        List<Menu> menuList = menuMapper.queryMenuByRoleId(roleId);
        Map<String, String> mapMenu = new HashMap<>();
        Map<String, String> mapRegion = new HashMap<>();
        //角色拥有的菜单
        for (Menu menu : menuList) {
            mapMenu.put(menu.getId(), menu.getId());
        }
        //角色拥有的按钮
        List<Region> regionList = regionMapper.queryRegionByRoleId(roleId);
        for (Region region : regionList) {
            mapRegion.put(region.getId(), region.getId());
        }
        // 所有菜单包含按钮
        List<TreeNode> list = menuService.queryAllMenu(true);
        //获取所有可用的菜单和按钮集合
        checkTree(mapMenu, mapRegion, list);
        return list;
    }

    //菜单和按钮选中的条件
    private void checkTree(Map<String, String> mapMenu, Map<String, String> mapRegion, List<TreeNode> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (TreeNode treeNode : list) {
            if (null == treeNode) {
                continue;
            }
            if ("menu".equals(treeNode.getAttributes()) && null != mapMenu && mapMenu.containsKey(treeNode.getId())) {
                treeNode.setChecked(true);
            }
            if ("region".equals(treeNode.getAttributes()) && null != mapRegion && mapRegion.containsKey(treeNode.getId())) {
                treeNode.setChecked(true);
            }
            checkTree(mapMenu, mapRegion, treeNode.getChildren());
        }
    }

    /**
     * 保存角色的权限信息
     *
     * @param roleId
     * @param listMenu   菜单
     * @param listRegion 按钮
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveAuthByRoleId(String roleId, List<String> listMenu, List<String> listRegion) throws Exception {
        log.info("保存角色的权限信息方法开始");
        if (StringUtils.isBlank(roleId)) {
            throw new BusinessException("获取角色信息失败，请稍后重试！");
        }
        //删除角色对应的菜单权限
        QueryWrapper<RoleMenu> wrapperRoleMenu = new QueryWrapper<>();
        wrapperRoleMenu.eq("ROLE_ID", roleId);
        roleMenuService.remove(wrapperRoleMenu);
        List<RoleMenu> roleMenuList = new ArrayList<>();
        if (null != listMenu && listMenu.size() > 0) {
            for (String menuId : listMenu) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(roleId);
                roleMenu.setAddTime(LocalDateTime.now());
                roleMenuList.add(roleMenu);
            }
        }
        if (roleMenuList != null && roleMenuList.size() > 0) {
            roleMenuService.saveBatch(roleMenuList);
        }
        //删除角色对应的按钮权限
        QueryWrapper<RoleRegion> wrapperRegion = new QueryWrapper<>();
        wrapperRegion.eq("ROLE_ID", roleId);
        roleRegionService.remove(wrapperRegion);
        List<RoleRegion> roleRegionList = new ArrayList<>();
        if (null != listRegion && listRegion.size() > 0) {
            for (String regionId : listRegion) {
                RoleRegion roleRegion = new RoleRegion();
                roleRegion.setRegionId(regionId);
                roleRegion.setRoleId(roleId);
                roleRegion.setAddTime(LocalDateTime.now());
                roleRegionList.add(roleRegion);
            }
        }
        if (roleRegionList != null && roleRegionList.size() > 0) {
            roleRegionService.saveBatch(roleRegionList);
        }
        log.info("保存角色的权限信息方法结束");
    }


    /**
     * 类型，机构等中文的转换
     *
     * @param list
     * @return
     * @throws Exception
     */
    public List<Role> switchedListRole(List<Role> list) throws Exception {
        Map<String, Organization> map = organizationService.getCacheOrganizationMap();
        Map<String, String> mapRoleStatus = dicvalueService.getCacheDicValueMap(SystemEnum.SYS_STATUS.getCode());
        Map<String, String> mapRoleType = dicvalueService.getCacheDicValueMap(SystemEnum.SYS_ROLE_TYPE.getCode());
        for (Role role : list) {
            if (null == role) {
                continue;
            }
            if (null != map && map.containsKey(role.getOrgId())) {
                Organization organization = map.get(role.getOrgId());
                if (null == organization) {
                    continue;
                }
                role.setStrOrgName(organization.getFullName());
            }
            if (null != mapRoleStatus && mapRoleStatus.containsKey(String.valueOf(role.getStatus()))) {
                role.setStrStatus(mapRoleStatus.get(String.valueOf(role.getStatus())));
            }

            if (null != mapRoleType && mapRoleType.containsKey(String.valueOf(role.getType()))) {
                role.setStrType(mapRoleType.get(String.valueOf(role.getType())));
            }
        }
        return list;
    }


    /**
     * 查询条件
     *
     * @param role
     * @return
     * @throws Exception
     */
    private QueryWrapper<Role> getQueryWrapper(Role role) throws Exception {
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("ADD_TIME");
        if (null == role) {
            return wrapper;
        }
        //查询当前登录人所在机构以及下级机构用户信息
        List<String> listOrganization = organizationService.queryOrganizationIds(redisCacheManager.getLoginUserInfo().getOrgId());
        wrapper.in("ORG_ID", listOrganization);
        if (StringUtils.isNotBlank(role.getStrOrgName())) {
            List<String> list = JSONArray.parseArray(role.getStrOrgName(), String.class);
            if (!CollectionUtils.isEmpty(list)) {
                wrapper.in("ORG_ID", list);
            }
        }
        if (StringUtils.isNotBlank(role.getName())) {
            wrapper.like("NAME", role.getName());
        }
        if (StringUtils.isNotBlank(role.getStrType())) {
            List<Integer> list = JSONArray.parseArray(role.getStrType(), Integer.class);
            if (!CollectionUtils.isEmpty(list) && null != list.get(0)) {
                wrapper.in("TYPE", list);
            }
        }
        if (StringUtils.isNotBlank(role.getStrStatus())) {
            List<Integer> list = JSONArray.parseArray(role.getStrStatus(), Integer.class);
            if (!CollectionUtils.isEmpty(list) && null != list.get(0)) {
                wrapper.in("STATUS", list);
            }
        }
        return wrapper;
    }
}
